#include "EventChannel.h"
#include <sys/socket.h>
#include <sys/uio.h>  // readv
#include <unistd.h>
#include <sys/timerfd.h>

#include"Logger.h"
using namespace Log;
namespace wjc {
	EventChannel::EventChannel(Core* core) :
		core_(core),
		eventfd_(createEventfd()),
		channel_(new Channel(core, eventfd_))
	{
		channel_->setReadCallback(std::bind(&EventChannel::handleRead, this));
	}
	EventChannel::~EventChannel() {

	}

	void EventChannel::enable() {
		channel_->enableReading();
	}

	void EventChannel::trigger() {
		uint64_t one = 1;
		ssize_t n = net::sockets::write(eventfd_, &one, sizeof one);
		if (n != sizeof one)
		{
			LOG_ERROR << "EventChannel::wakeup() writes " << n << " bytes instead of 8";
		}
	}

	void EventChannel::handleRead() {
		uint64_t one = 1;
		while (true) {
			ssize_t n = net::sockets::read(eventfd_, &one, sizeof one);
			Timestamp now = Timestamp::now();
			LOG_TRACE << "EventChannel::handleRead() " << n << " at " << now.toString();
			if (n != sizeof one)
			{
				break;
				LOG_ERROR << "EventChannel::handleRead() reads " << n << " bytes instead of 8";
			}

			if (onEvent_)
				onEvent_();
		}
	}


	int EventChannel::createEventfd()
	{
		int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
		if (evtfd < 0)
		{
			LOG_SYSERR << "Failed in eventfd";
			abort();
		}
		return evtfd;
	}
}